<?php

namespace backend\modules\admin\models;

use Yii;
use yii\helpers\FileHelper;
use common\components\Helper;
use backend\models\Clients;
use backend\models\Extensions;
use backend\modules\languages\models\Overrides;

/**
 * This is the model class for table "{{%menu_types}}".
 *
 * @property int $id
 * @property string $menutype
 * @property string $title
 * @property string $description
 * @property int $client_id
 */
class MenuTypes extends \yii\db\ActiveRecord
{

    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return '{{%menu_types}}';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['client_id'], 'integer'],
            [['menutype', 'title'], 'required'],
            [['menutype'], 'string', 'max' => 24],
            [['title'], 'string', 'max' => 48],
            [['description'], 'string', 'max' => 255],
            [['menutype'], 'unique'],
            [['menutype'], 'match', 'pattern' => '/^[a-z]\w*$/i']
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('rbac-admin', 'ID'),
            'menutype' => Yii::t('rbac-admin', 'MENU_TYPE'),
            'title' => Yii::t('rbac-admin', 'TITLE'),
            'description' => Yii::t('rbac-admin', 'DESCRIPTION'),
            'client_id' => Yii::t('rbac-admin', 'CLIENT'),
            'search' => Yii::t('common', 'SEARCH')
        ];
    }

    public function getOptions($client_id, $type = '', $route = '')
    {
        $client = Clients::findOne($client_id);
        if (is_null($client)) {
            return false;
        }

        $options = [];

        $this->addCustomOptions($options);
        if ($type && $type !== 'module') {
            foreach ($options as $option) {
                foreach ($option['items'] as $item) {
                    if ($type === $item->type) {
                        $item->client = $client->name;
                        return $item;
                    }
                }
            }
        }

        $this->addXmlOptions($options, $client);

        $extensions = Extensions::find()
            ->select(['id', 'element', 'client_id', 'manifest_cache', 'enabled', 'status'])
            ->where(['type' => 'module'])
            ->all();

        foreach ($extensions as $extension) {
            $this->addXmlOptions($options, $client, $extension);
        }

        uksort($options, function ($a, $b) {
            return strcasecmp(iconv('UTF-8', 'GBK', $a), iconv('UTF-8', 'GBK', $b));
        });

        if ($type && $type === 'module') {
            foreach ($options as $option) {
                foreach ($option['items'] as $item) {
                    if ($route === $item->route) {
                        $item->client = $client->name;
                        return $item;
                    }
                }
            }
        } else {
            return $options;
        }
    }

    private function addCustomOptions(&$options)
    {
        $list = [];

        $object = new \stdClass();
        $object->title = 'MENUS_TYPE_EXTERNAL_URL';
        $object->description = 'MENUS_TYPE_EXTERNAL_URL_DESC';
        $object->langCat = 'rbac-admin';
        $object->route = '';
        $object->type = 'url';
        $object->path = '';
        $list[Yii::t($object->langCat, $object->title)] = $object;

        $object = new \stdClass();
        $object->title = 'MENUS_TYPE_ALIAS';
        $object->description = 'MENUS_TYPE_ALIAS_DESC';
        $object->langCat = 'rbac-admin';
        $object->route = '';
        $object->type = 'alias';
        $object->path = '';
        $list[Yii::t($object->langCat, $object->title)] = $object;

        $object = new \stdClass();
        $object->title = 'MENUS_TYPE_SEPARATOR';
        $object->description = 'MENUS_TYPE_SEPARATOR_DESC';
        $object->langCat = 'rbac-admin';
        $object->route = '';
        $object->type = 'separator';
        $object->path = '';
        $list[Yii::t($object->langCat, $object->title)] = $object;

        $object = new \stdClass();
        $object->title = 'MENUS_TYPE_HEADING';
        $object->description = 'MENUS_TYPE_HEADING_DESC';
        $object->langCat = 'rbac-admin';
        $object->route = '';
        $object->type = 'heading';
        $object->path = '';
        $list[Yii::t($object->langCat, $object->title)] = $object;

        uksort($list, function ($a, $b) {
            return strcasecmp(iconv('UTF-8', 'GBK', $a), iconv('UTF-8', 'GBK', $b));
        });

        $options[Yii::t('rbac-admin', 'MENUS_TYPE_SYSTEM')] = [
            'name' => 'system',
            'items' => $list
        ];
    }

    private function addXmlOptions(&$options, $client, $extension = null)
    {
        if (Helper::getClient() === $client->name) {
            $appId = Yii::$app->id;
            $langCatPrefix = '';
        } else {
            $appMainConfig = require Yii::getAlias('@' . $client->name . '/config/main.php');
            $appId = $appMainConfig['id'];
            $langCatPrefix = '@' . $client->name . '/';
        }

        if (is_null($extension)) {
            $metadataPath = Yii::getAlias('@' . $client->name . '/metadata');
            if (is_dir($metadataPath)) {
                $xmlFiles = FileHelper::findFiles($metadataPath, ['only' => ['*.xml']]);
                if ($xmlFiles) {
                    $tmp = [];
                    foreach ($xmlFiles as $xmlFile) {
                        $xml = simplexml_load_file($xmlFile);
                        $o = new \stdClass();
                        $o->title = (string)$xml->layout->attributes()->title;
                        $o->description = (string)$xml->layout->message;
                        $o->langCat = $langCatPrefix . $client->name;
                        $o->route = '@' . $appId . '/' . (string)$xml->layout->route;
                        $o->type = (string)$xml->layout->type;
                        $o->path = substr($xmlFile, strlen(Yii::getAlias('@' . $client->name)));

                        $title = Yii::t($o->langCat, $o->title);
                        $tmp[$title] = $o;
                    }
                    uksort($tmp, function ($a, $b) {
                        return strcasecmp(iconv('UTF-8', 'GBK', $a), iconv('UTF-8', 'GBK', $b));
                    });
                    $modTitle = Yii::t($langCatPrefix . $client->name, strtoupper($appId));
                    $options[$modTitle] = [
                        'name' => $appId,
                        'items' => $tmp
                    ];
                }
            }
        } else {
            $element = strpos($extension->element, 'mod_') === 0 ? substr($extension->element, 4) : $extension->element;
            $metadataPath = Yii::getAlias('@' . $client->name . '/modules/' . $element . '/metadata');
            if (is_dir($metadataPath)) {
                $xmlFiles = FileHelper::findFiles($metadataPath, ['only' => ['*.xml']]);
                $langCat = $extension->manifest_cache['langCat'] ?? null;
                $tmp = [];
                foreach ($xmlFiles as $xmlFile) {
                    $xml = simplexml_load_file($xmlFile);
                    $o = new \stdClass();
                    $o->title = (string)$xml->layout->attributes()->title;
                    $o->description = (string)$xml->layout->message;
                    $o->langCat = is_null($langCat) ? null : $langCatPrefix . $langCat;
                    $o->route = '@' . $appId . '/' . $element . '/' . (string)$xml->layout->route;
                    $o->type = (string)$xml->layout->type;
                    $o->path = substr($xmlFile, strlen(Yii::getAlias('@' . $client->name)));

                    $title = Yii::t($o->langCat ?? 'common', $o->title);
                    $tmp[$title] = $o;
                }
                uksort($tmp, function ($a, $b) {
                    return strcasecmp(iconv('UTF-8', 'GBK', $a), iconv('UTF-8', 'GBK', $b));
                });
                $modTitle = Yii::t((is_null($langCat) ? 'common' : $langCatPrefix . $langCat), strtoupper($extension->element));
                $options[$modTitle] = [
                    'name' => $element,
                    'items' => $tmp
                ];
            }
        }
    }

    public function getTitleKey()
    {
        return $this->hasOne(Overrides::class, ['client_id' => 'client_id', 'override_key' => 'title']);
    }

    public function getDescKey()
    {
        return $this->hasOne(Overrides::class, ['client_id' => 'client_id', 'override_key' => 'description']);
    }
}
